#ifndef BDC22DE7_6811_4DED_96EF_01104DECE8C4
#define BDC22DE7_6811_4DED_96EF_01104DECE8C4

#include <iostream>
#include <cstring>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <pthread.h>
#include "ThreadPool.hpp"
#include "Log.hpp"
#include "Init.hpp"
#include "Daemon.hpp"

Log lg;

enum{
	SOCKET_ERROR = 1,
	BIND_ERROR,
	LISTEN_ERROR
};

class Tcpserver;

//(sockfd,clientip,port,this)
class ThreadData{
public:
	ThreadData(int sockfd,const char* clientip,uint16_t port,Tcpserver* tcp):port_(port),sockfd_(sockfd),
	clientip_(clientip),tcp_(tcp)
	{}
public:
	Tcpserver* tcp_;
	int sockfd_;
	std::string clientip_;
	uint16_t port_;
};

const uint16_t serverport = 8080;
const std::string serverip = "0.0.0.0";	
const int backlog = 12;
const int size = 4096;

class Tcpserver{
public:
	Tcpserver(uint16_t port = serverport,std::string ip = serverip):ip_(ip),port_(port)
	{}
	void Init()
	{
		listensock = socket(AF_INET,SOCK_STREAM,0);
		if(listensock < 0)
		{
			lg(Fatal,"socket error , errno : %d,errstring:%s",errno,strerror(errno));
			exit(SOCKET_ERROR);
		}
		lg(Info,"socket success");
		int opt = 1;
		setsockopt(listensock, SOL_SOCKET, SO_REUSEADDR|SO_REUSEPORT, &opt, sizeof(opt)); // 防止偶发性的服务器无法进行立即重启
		struct sockaddr_in server;
		server.sin_port = htons(port_);
		server.sin_family = AF_INET;
		inet_aton(ip_.c_str(),&server.sin_addr);
		if(bind(listensock,(const sockaddr*)&server,sizeof(server)))
		{
			lg(Fatal,"bind error , errno : %d,errstring:%s",errno,strerror(errno));
			exit(BIND_ERROR);
		}
		lg(Info,"bind success");
		if(listen(listensock,backlog)){
			lg(Fatal,"listen error , errno : %d,errstring:%s",errno,strerror(errno));
			exit(LISTEN_ERROR);
		}
		lg(Info,"listen success");
	}
	// static void* handler(void* args)
	// {
	// 	pthread_detach(pthread_self());         // 线程分离
	// 	ThreadData* td = static_cast<ThreadData*>(args);
	// 	td->tcp_->Service(td->sockfd_,td->clientip_,td->port_);
	// 	return nullptr;
	// }
	void Start()
	{
		Daemon();
		ThreadPool<Task>::Initializer()->start();
		// signal(SIGCHLD,SIG_IGN);       // 解决多进程等待的方法二
		// lg.Enable(Classfile);
		lg(Info,"tcpserver is running....");
		for( ; ;){
			struct sockaddr_in client;
			socklen_t len = sizeof(client);
			int sockfd = accept(listensock,(sockaddr*)&client,&len);
			if(sockfd < 0)
			{
				lg(Fatal,"accept error , errno : %d,errstring:%s",errno,strerror(errno));
			}
			char clientip[32];
			inet_ntop(AF_INET,&client.sin_addr,clientip,sizeof(client));
			uint16_t port = ntohs(client.sin_port);
			// sleep(1);
			// std::string clientip = inet_ntoa(client.sin_addr);
			lg(Info,"accept success,sockfd : %d,clientip : %s,clientport : %d",sockfd,clientip,port);
			//version 1  ------- 单进程
			// Service(sockfd,clientip,port);
			// close(sockfd);

			//version2    -------- 多进程
			// pid_t id = fork();        // ----创建进程的成本太高了
			// if(id == 0)
			// {
			// 	close(listensock);
			// 	if(fork() > 0) exit(0);            // 解决多进程等待方法1
			// 	Service(sockfd,clientip,port);      /// 让孙子进程去处理，且孙子进程的父亲已经退出，都归属system管理
			// 	close(sockfd);
			// 	exit(0);
			// }
			// close(sockfd);
			// pid_t rid = waitpid(id,nullptr,0);
			// (void)rid;

			//version3   ------- 多线程
			// ThreadData* td = new ThreadData(sockfd,clientip,port,this);
			// pthread_t tid;
			// pthread_create(&tid,nullptr,handler,td);

			//version4  --------- 线程池
			Task t(sockfd,clientip,port);
			ThreadPool<Task>::Initializer()->push(t);
		}
	}
	// void Service(int sockfd,const std::string& clientip,const uint16_t port)
	// {
	// 	char buffer[size];
	// 	while(true)
	// 	{
	// 		int n = read(sockfd,buffer,sizeof(buffer));
	// 		if(n > 0)
	// 		{
	// 			buffer[n] = 0; //'/0'
	// 			std::cout << "client say# " << buffer << std::endl;
	// 			std::string answer = "server echo# ";
	// 			answer += buffer;
	// 			write(sockfd,answer.c_str(),answer.size());
	// 		}
	// 		else if(n == 0)
	// 		{
	// 			lg(Info,"%s : %d quit",clientip.c_str(),port);
	// 			break;
	// 		}
	// 		else{
	// 			lg(Warnning,"%s read error",clientip.c_str());
	// 			break;
	// 		}
	// 	}
	//}
private:
	std::string ip_;
	uint16_t port_;
	int listensock;
	// ThreadPool<Task>* tasks;
};

#endif /* BDC22DE7_6811_4DED_96EF_01104DECE8C4 */
